import 'package:flutter/material.dart';
import 'package:flutter_demo/pages/base/layout_params/physical_model_page.dart';
import 'package:flutter_demo/pages/page_with_title.dart';
import 'package:flutter_demo/widgets/app_widgets.dart';

import '../../../conf/m3.dart';

class ClipPage extends PageWithTitle {
  const ClipPage({super.key})
      : super("裁剪组件(ClipRect、ClipRRect、ClipOval、ClipPath)");

  @override
  List<Widget> buildContentWidgets(BuildContext context) {
    return const [
      PrimaryTitle("简介"),
      BodyText("与android的clipToBounds clipToPadding类似，Flutter也提供了边界裁剪组件"
          "，部分组件的使用是没有限制绘制边界的，通过裁剪组件实现绘制边界限制"),
      AppSpacer.large,
      LabelText("自定义组件进行绘制的时候就没有边界限制，若内部不通过canvas设置裁剪区域，则可以绘制到组件外面"),
      SizedBox(
        width: 160,
        height: 160,
        child: _DrawOverBounds(),
      ),
      AppSpacer.large,
      Wrap(
        children: [
          ClipRect(
            child: _DrawOverBounds(),
          ),
        ],
      ),
      AppSpacer.mini,
      UlItem("ClipRect"),
      BodyText("裁剪矩形，按照组件边界裁剪一下"),
      LabelText("- clipper 自定义裁剪，不建议设置，Flutter提供了其它常用样式的裁剪，参考下方组件"),
      LabelText("- clipBehavior 裁剪行为，默认Clip.hardEdge，因为矩形裁剪没有斜边、曲边，无需抗锯齿"),
      LabelText("- child 将根据子组件的边界进行裁剪，实际内部实现就是在绘制子组件前先设置画布裁剪"),
      AppSpacer.large,
      Wrap(
        children: [
          ClipRRect(
            borderRadius: M3.connerRadiusMedium,
            child: _DrawOverBounds(),
          ),
        ],
      ),
      AppSpacer.mini,
      UlItem("ClipRRect"),
      BodyText("裁剪圆角矩形，默认设置了抗锯齿"),
      LabelText("- borderRadius 裁剪的圆角设置"),
      AppSpacer.large,
      Wrap(
        children: [
          ClipOval(
            child: _DrawOverBounds(),
          ),
        ],
      ),
      AppSpacer.mini,
      UlItem("ClipOval"),
      BodyText("椭圆裁剪，将根据子组件的尺寸创建内接椭圆进行裁剪，若子组件为正方形，则裁剪图形就是圆形了"),
      AppSpacer.large,
      Row(
        children: [
          LabelText("圆形 CircleBorder"),
          AppSpacer.mini,
          ClipPath(
            clipper: ShapeBorderClipper(shape: CircleBorder()),
            child: _DrawOverBounds(),
          ),
        ],
      ),
      Row(
        children: [
          LabelText("椭圆形 OvalBorder"),
          AppSpacer.mini,
          ClipPath(
            clipper: ShapeBorderClipper(shape: OvalBorder()),
            child: _DrawOverBounds(),
          ),
        ],
      ),
      Row(
        children: [
          LabelText("跑道 CircleBorder"),
          AppSpacer.mini,
          ClipPath(
            clipper: ShapeBorderClipper(shape: StadiumBorder()),
            child: _DrawOverBounds(),
          ),
        ],
      ),
      Row(
        children: [
          LabelText("圆角 RoundedRectangleBorder"),
          AppSpacer.mini,
          ClipPath(
            clipper: ShapeBorderClipper(
                shape: RoundedRectangleBorder(
                    borderRadius: M3.connerRadiusMedium)),
            child: _DrawOverBounds(),
          ),
        ],
      ),
      Row(
        children: [
          LabelText("圆角平滑过渡 ContinuousRectangleBorder"),
          AppSpacer.mini,
          ClipPath(
            clipper: ShapeBorderClipper(
                shape: ContinuousRectangleBorder(
                    borderRadius: M3.connerRadiusMedium)),
            child: _DrawOverBounds(),
          ),
        ],
      ),
      Row(
        children: [
          LabelText("切角 BeveledRectangleBorder"),
          AppSpacer.mini,
          ClipPath(
            clipper: ShapeBorderClipper(
                shape: BeveledRectangleBorder(
                    borderRadius: M3.connerRadiusMedium)),
            child: _DrawOverBounds(),
          ),
        ],
      ),
      Wrap(
        crossAxisAlignment: WrapCrossAlignment.center,
        children: [
          LabelText("星星 StarBorder"),
          AppSpacer.mini,
          ClipPath(
            clipper: ShapeBorderClipper(shape: StarBorder()),
            child: _DrawOverBounds(),
          ),
          AppSpacer.mini,
          //points指定角的数量，innerRadiusRatio指定凹陷部位位置[0,1]表示在圆心到外接圆上的距离，若为1就表现为正多边形
          ClipPath(
            clipper: ShapeBorderClipper(
                shape: StarBorder(points: 3, innerRadiusRatio: 0.5)),
            child: _DrawOverBounds(),
          ),
          AppSpacer.mini,
          ClipPath(
            clipper: ShapeBorderClipper(
                shape: StarBorder(points: 6, innerRadiusRatio: 0.6)),
            child: _DrawOverBounds(),
          ),
          AppSpacer.mini,
          //pointRounding 指定角的圆滑度
          ClipPath(
            clipper: ShapeBorderClipper(
                shape: StarBorder(
                    points: 6, innerRadiusRatio: 0.6, pointRounding: 0.5)),
            child: _DrawOverBounds(),
          ),
          AppSpacer.mini,
          //valleyRounding 指定凹陷的圆滑度
          ClipPath(
            clipper: ShapeBorderClipper(
                shape: StarBorder(
                    points: 6,
                    innerRadiusRatio: 0.6,
                    pointRounding: 0.5,
                    valleyRounding: 0.5)),
            child: _DrawOverBounds(),
          ),
          AppSpacer.mini,
          //squash 指定比例，星星的占用空间可以视为正方形，若子组件为长方形时星星会居中，这个为拉伸星星到填充满子组件的比例
          ClipPath(
            clipper: ShapeBorderClipper(
                shape: StarBorder(
                    points: 6,
                    innerRadiusRatio: 0.6,
                    pointRounding: 0.5,
                    valleyRounding: 0.5,
                    squash: 1)),
            child: _DrawOverBounds(),
          ),
        ],
      ),
      AppSpacer.mini,
      UlItem("ClipPath"),
      BodyText("路径裁剪，按照路径裁剪子组件，自定义裁剪时使用这个组件"),
      LabelText("- clipper 实现自定义裁剪，返回一个CustomClipper<Path>实例来提供裁剪路径"),
      NoticeText("Flutter已经提供ShapeBorderClipper和大量ShapeBorder效果，足以满足常见需求"),
      NoticeText("若需要阴影效果，详见PhysicalShape"),
      PageLink(PhysicalModelPage()),
    ];
  }
}

class _DrawOverBounds extends StatelessWidget {
  const _DrawOverBounds();

  @override
  Widget build(BuildContext context) {
    return UnconstrainedBox(
      child: CustomPaint(
        size: const Size(120, 80),
        painter: _OverBoundsPainter(),
      ),
    );
  }
}

class _OverBoundsPainter extends CustomPainter {
  _OverBoundsPainter();

  final _drawPaint = Paint();

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawRect(
      Rect.fromLTRB(0, 0, size.width, size.height),
      _drawPaint..color = Colors.yellow,
    );
    canvas.drawCircle(
      Offset.zero,
      size.shortestSide / 2,
      _drawPaint..color = Colors.red,
    );
    canvas.drawCircle(
      Offset(size.width, 0),
      size.shortestSide / 2,
      _drawPaint..color = Colors.green,
    );
    canvas.drawCircle(
      Offset(size.width, size.height),
      size.shortestSide / 2,
      _drawPaint..color = Colors.blue,
    );
    canvas.drawCircle(
      Offset(0, size.height),
      size.shortestSide / 2,
      _drawPaint..color = Colors.black,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}
